﻿using Iot.Models;
using Microsoft.AspNetCore.SignalR;
using static Iot.ServerWorker;
using System.Text.Json;
using System.Text;
using MQTTnet.Server;
using Iot.Hubs;
using MQTTnet;
using MQTTnet.Protocol;
using System;

namespace Iot
{
    public class ServerWorker : BackgroundService
    {
        private static MqttServer? server;
        private static ILogger<ServerWorker>? _logger;
        private static IHubContext<MessageHub>? _hubContext;
        private static IClientWorker? _clientWorker;

        public ServerWorker(IServiceProvider provider)
        {
            _logger = provider.GetRequiredService<ILogger<ServerWorker>>();
            _hubContext = provider.GetRequiredService<IHubContext<MessageHub>>();
            _clientWorker = provider.GetRequiredService<IClientWorker>();
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await StartMqttServer();
        }

        static async Task StartMqttServer()
        {
            string username = "admin";//用户名
            string password = "admin";//密码

            //var mqttFactory = new MqttFactory(new ConsoleLogger());
            var mqttFactory = new MqttFactory();

            var options = new MqttServerOptionsBuilder().WithDefaultEndpoint().Build();

            server = mqttFactory.CreateMqttServer(options);
            server.ValidatingConnectionAsync += e =>
            {
                if (e.UserName != username || e.Password != password)
                {
                    e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
                }

                return Task.CompletedTask;
            };


            server.ClientSubscribedTopicAsync += MqttServer_ClientSubscribedTopicAsync;
            server.ClientUnsubscribedTopicAsync += MqttServer_ClientUnsubscribedTopicAsync;

            server.ClientConnectedAsync += MqttServer_ClientConnectedAsync;
            server.ClientDisconnectedAsync += MqttServer_ClientDisconnectedAsync;

            server.ApplicationMessageNotConsumedAsync += Server_ApplicationMessageNotConsumedAsync;


            await server.StartAsync();

            if (server.IsStarted)
            {
                _logger?.LogInformation($"{DateTime.Now} 服务器已启动");
            }
            else
            {
                _logger?.LogError($"{DateTime.Now} 服务器启动失败");
                System.Threading.Thread.Sleep(5000);
                await StartMqttServer();

            }
        }

        private static async Task Server_ApplicationMessageNotConsumedAsync(ApplicationMessageNotConsumedEventArgs arg)
        {
            var msgStr = Encoding.UTF8.GetString(arg.ApplicationMessage.PayloadSegment.Array!);
            var msg = JsonSerializer.Deserialize<MQTTMessage>(msgStr);
            //_logger?.LogInformation($"{DateTime.Now} 收到来自客户端 {arg.SenderId} 的消息: {msg}");

            //更新开关状态
            if (msg?.To == "SERVER" && arg.ApplicationMessage.Topic == MQTTTOPIC.UPDATE)
            {
                SwitchDevice remote = new()
                {
                    DeviceMAC = msg?.From,
                    GPIO = Convert.ToInt32(msg?.GPIO),
                    Status = msg?.Msg == "0" ? SwitchDeviceStatus.Off : SwitchDeviceStatus.On
                };
                UpdateSwitchStatue(remote);
            }

            //处理声控代码
            if (msg?.From == "SOUND")
            {
                //筛选有用消息
                if (msg?.Msg!.Length == 4)
                {
                    var snid = msg.Msg[..3];
                    var state = msg.Msg.Substring(3,1);
                    var list = AppData.AppConfig.Switchs;
                    //查找开关
                    var find = list.Where(p => p.SNID == snid);
                    if (find.Any())
                    {
                        var active = find.First();
                        active.Status = state == "0" ? SwitchDeviceStatus.Off : SwitchDeviceStatus.On;
                        //向设备发送控制指令
                        if (_clientWorker != null)
                            await _clientWorker.PublishAsync(MQTTTOPIC.CONTROL, new MQTTMessage() { Msg = $"{state}", To = active.DeviceMAC, GPIO = active.GPIO });
                       
                        UpdateSwitchStatue(active);
                    }
                }
            }

            //软件控制或本地按键控制，都会更新页面
            if(_hubContext != null)
                AppData.HUB?.SendCoreAsync("SendMessage", new object[] { "ReceiveResponse", "sadfasf" });
        }

        private static void UpdateSwitchStatue(SwitchDevice s)
        {
            var switchs = AppData.AppConfig.Switchs;
            var find = switchs.Where(p => p.DeviceMAC == s.DeviceMAC && p.GPIO == s.GPIO);
            if (find.Any())
            {
                foreach (var item in find)
                {
                    item.Status = s.Status;
                }
            }
        }

        private static Task MqttServer_ClientDisconnectedAsync(ClientDisconnectedEventArgs arg)
        {
            //_logger?.LogWarning($"{DateTime.Now} 客户端 {arg.ClientId} 已断开");
            SwitchDevice s = new()
            {
                DeviceMAC = arg.ClientId,
                Status = SwitchDeviceStatus.None
            };
            
            var switchs = AppData.AppConfig.Switchs;
            var find = switchs.Where(p => p.DeviceMAC == s.DeviceMAC);
            if (find.Any())
            {
                foreach (var item in find)
                {
                    item.Status = s.Status;
                }
            }

            return Task.CompletedTask;
        }

        private static Task MqttServer_ClientConnectedAsync(ClientConnectedEventArgs arg)
        {
            //_logger?.LogInformation($"{DateTime.Now} 客户端 {arg.ClientId} 已连接");
            return Task.CompletedTask;
        }

        private static Task MqttServer_ClientUnsubscribedTopicAsync(ClientUnsubscribedTopicEventArgs arg)
        {
            //_logger?.LogInformation($"{DateTime.Now} 客户端 {arg.ClientId} 已订阅 {arg.TopicFilter}");
            return Task.CompletedTask;
        }

        private static Task MqttServer_ClientSubscribedTopicAsync(ClientSubscribedTopicEventArgs arg)
        {
            //_logger.LogInformation($"{DateTime.Now} 客户端 {arg.ClientId} 已取消订阅 {arg.TopicFilter}");
            SwitchDevice s = new()
            {
                DeviceMAC = arg.ClientId,
                Status = SwitchDeviceStatus.None
            };

            var switchs = AppData.AppConfig.Switchs;
            var find = switchs.Where(p => p.DeviceMAC == s.DeviceMAC);
            if (find.Any())
            {
                foreach (var item in find)
                {
                    item.Status = s.Status;
                }
            }

            return Task.CompletedTask;
        }
    }
}
